home *** CD-ROM | disk | FTP | other *** search
/ CD Fun House 8 / CD Funhouse Version 8.0 - Wayzata Technology (7013) (1993).iso / pc / pc / cards / bidding / bidding.c next >
C/C++ Source or Header  |  1989-02-14  |  11KB  |  423 lines

  1. /* bidding.c */
  2. /*
  3.             Bridge Bidder    Version 2.0
  4.             by Nathan Glasser
  5.             nathan@brokaw.lcs.mit.edu (internet)
  6.             nathan@mit-eddie.uucp (usenet)
  7.  
  8.             February, 1989
  9. ------------------------------------------------------------------------------
  10. Copyright 1988, 1989 by Nathan Glasser.
  11. You may feel free to distribute this program in its current form.
  12. Please do not remove this copyright information.
  13. */
  14.  
  15. #include "bidding.h"
  16.  
  17. int num_hands = DEF_NUM_HANDS;
  18.  
  19. char *vuln_relative[] = {"YOUR SIDE","OTHER SIDE"};
  20. char *vuln_absolute[] = {"1ST SIDE","2ND SIDE","NEITHER SIDE","BOTH SIDES"};
  21. char *suit_strings[4] = {"SPADES","HEARTS","DIAMONDS","CLUBS"};
  22. char *vuln_format[2][2] = {
  23.   {"DECLARER SIDE","DEFENDER SIDE"},
  24.   {"VERTICAL SIDE","HORIZONTAL SIDE"}};
  25.  
  26. #define PASSED_OUT(pdeal) \
  27.     ((pdeal)->num_bids == 4 && (pdeal)->bids->bid.suit == PASS)
  28.  
  29. main(argc,argv)
  30. int argc;
  31. char **argv;
  32. {
  33.     deal *deals;
  34.     int i,j;
  35.     int num_hands_left;
  36.     int hand_num;
  37.  
  38.     if (argc > 1)
  39.     num_hands = atoi(argv[1]);
  40.     printf("Dealing %d hands...\n",num_hands_left = num_hands);
  41.  
  42.     deals = (deal *)malloc(num_hands * sizeof(deal));
  43.  
  44.     srandom((unsigned)time(NULL));
  45.  
  46.     for (i = 0; i < num_hands; i++)
  47.     deal_hands(&deals[i]);
  48.  
  49.     /* Accept bids */
  50.     while (num_hands_left)
  51.     {
  52.     hand_num = random() % num_hands;
  53.  
  54.     if (deals[hand_num].bidding_done)
  55.         continue;
  56.     clear_screen();
  57.  
  58.         for (;;)
  59.         {
  60.             print_bidding(stdout,&deals[hand_num],-2);
  61.             printf("YOUR HAND (%s VULNERABLE):\n",
  62.               (deals[hand_num].vulnerability <= RELATIVE) ?
  63.               vuln_relative[(deals[hand_num].num_bids & 1) ^ 
  64.               deals[hand_num].vulnerability] :
  65.               vuln_absolute[deals[hand_num].vulnerability]);
  66.             print_hand(stdout,
  67.               deals[hand_num].hands[deals[hand_num].num_bids % 4]);
  68.             if (!accept_bid(&deals[hand_num]))
  69.                 break;
  70.             printf("Bad bid.\n\n");
  71.         }
  72.  
  73.     if (deals[hand_num].bidding_done)
  74.     {
  75.         num_hands_left--;
  76.         /* If hand was passed out */
  77.         if (PASSED_OUT(&deals[hand_num]))
  78.             display_complete_deal(&deals[hand_num],0);
  79.     }
  80.     }
  81.  
  82.     /* Accept opening leads */
  83.     for (hand_num = 0; hand_num < num_hands; hand_num++)
  84.     {
  85.         /* Make sure hand wasn't passed out */
  86.     if (PASSED_OUT(&deals[hand_num]))
  87.         continue;
  88.     clear_screen();
  89.     j = figure_out_leader(&deals[hand_num]);
  90.  
  91.         for (;;)
  92.         {
  93.             print_bidding(stdout,&deals[hand_num],j);
  94.             printf("YOUR HAND (%s VULNERABLE):\n",
  95.               (deals[hand_num].vulnerability <= RELATIVE) ?
  96.               vuln_relative[(j & 1) ^ 
  97.               deals[hand_num].vulnerability] :
  98.               vuln_absolute[deals[hand_num].vulnerability]);
  99.             print_hand(stdout,deals[hand_num].hands[j]);
  100.             if (!get_lead(&deals[hand_num],j))
  101.                 break;
  102.             printf("Bad lead.\n\n");
  103.         }
  104.  
  105.     display_complete_deal(&deals[hand_num],((j + 1) % 4));
  106.     }
  107.  
  108.     printf("All bidding complete.\n");
  109. }
  110.  
  111. display_complete_deal(pdeal,top_hand)
  112. deal *pdeal;
  113. int top_hand;
  114. {
  115.     print_complete_deal(stdout,pdeal,top_hand);
  116.     more();
  117.     log_deal(pdeal,top_hand);
  118. }
  119.  
  120. print_complete_deal(fp,pdeal,top_hand)
  121. FILE *fp;
  122. deal *pdeal;
  123. int top_hand;
  124. {
  125.     int i;
  126.     char top_h[4][80],left_h[4][80],right_h[4][80],bottom_h[4][80];
  127.  
  128.     format_hand(top_h,pdeal->hands[top_hand]);
  129.     format_hand(right_h,pdeal->hands[(top_hand + 1) % 4]);
  130.     format_hand(bottom_h,pdeal->hands[(top_hand + 2) % 4]);
  131.     format_hand(left_h,pdeal->hands[(top_hand + 3) % 4]);
  132.     fprintf(fp,"\t\t\tCOMPLETE DEAL (%s VULNERABLE):\n",
  133.       ((pdeal->vulnerability <= RELATIVE) ?
  134.       vuln_format[PASSED_OUT(pdeal)][(top_hand & 1) ^ pdeal->vulnerability] :
  135.       vuln_absolute[pdeal->vulnerability]));
  136.  
  137.     for (i = 0; i < 4; i++)
  138.         fprintf(fp,"\t\t\t%s\n",top_h[i]);
  139.     for (i = 0; i < 4; i++)
  140.         fprintf(fp,"%-43s%s\n",left_h[i],right_h[i]);
  141.     for (i = 0; i < 4; i++)
  142.         fprintf(fp,"\t\t\t%s\n",bottom_h[i]);
  143. }
  144.  
  145. print_bidding(fp,pdeal,your_position)
  146. FILE *fp;
  147. deal *pdeal;
  148. int your_position;
  149. {
  150.     bid *bids;
  151.     static char *bid_suits[] = {"S","H","D","C","NT","DB","RD","P"};
  152.     int bid_num = 0;
  153.     static char *bid_labels[] = {"*You*","LHO","Partner","RHO"};
  154.     static char *lead_labels[] = {"*You*","Dummy","Partner","Decl."};
  155.     char **labels;
  156.     int i;
  157.  
  158.     if (your_position != -1)
  159.     {
  160.         if (your_position < 0)
  161.     {
  162.         your_position = pdeal->num_bids;
  163.         labels = bid_labels;
  164.     }
  165.     else
  166.         labels = lead_labels;
  167.  
  168.     putc('\t',fp);
  169.     for (i = 0; i < 4; i++)
  170.         fprintf(fp,"\t%s",labels[(1000 + i - your_position) % 4]);
  171.     }
  172.     fprintf(fp,"\nBIDDING:\t--------------------------------\n");
  173.  
  174.     for (bids = pdeal->bids; bid_num < pdeal->num_bids; bids = bids->next)
  175.     {
  176.     if ((bid_num % 4) == 0)
  177.         putc('\t',fp);
  178.     if (bids->bid.suit <= RANK_USED)
  179.         fprintf(fp,"\t%d%s",bids->bid.rank,bid_suits[bids->bid.suit]);
  180.     else
  181.         fprintf(fp,"\t%s",bid_suits[bids->bid.suit]);
  182.     if ((++bid_num % 4) == 0)
  183.         putc('\n',fp);
  184.     }
  185.     if (bid_num % 4)
  186.     putc('\n',fp);
  187. }
  188.  
  189. accept_bid(pdeal)
  190. deal *pdeal;
  191. {
  192.     int ch;
  193.     int rank = -1,suit;
  194.     bid *newbid;
  195.     static int suit_cvt[] = {3,2,1,0,4};
  196.     bid *tmp;
  197.     int i;
  198.     
  199.     printf("\nEnter your bid: ");
  200.  
  201.     /* Get optional rank */
  202.     while (isspace(ch = getchar()));
  203.  
  204.     if (isdigit(ch))
  205.     {
  206.     rank = ch - '0';
  207.     while (isspace(ch = getchar()));
  208.     }
  209.  
  210.     /* Get suit, notrump, pass, double, or redouble */
  211.     if (islower(ch))
  212.     ch = toupper(ch);
  213.  
  214.     switch (ch)
  215.     {
  216.     case 'S':
  217.         suit = SPADES;
  218.         break;
  219.     case 'H':
  220.         suit = HEARTS;
  221.         break;
  222.     case 'D':
  223.         suit = (rank >= 0) ? DIAMONDS : DOUBLE;
  224.         break;
  225.     case 'C':
  226.         suit = CLUBS;
  227.         break;
  228.     case 'N':
  229.         suit = NOTRUMP;
  230.         break;
  231.     case 'P':
  232.         suit = PASS;
  233.         break;
  234.     case 'R':
  235.         suit = REDOUBLE;
  236.         break;
  237.     default:
  238.         suit = -1;
  239.         break;
  240.     }
  241.  
  242.     while (getchar() != '\n');
  243.     if (suit < 0)
  244.     return(1);
  245.  
  246.     /* Make sure numerical bid is ok */
  247.     if (suit <= RANK_USED)
  248.     {
  249.         if (rank < 1 || rank > 7)
  250.         return(1);
  251.     if (pdeal->num_bids > 0)
  252.         for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
  253.           tmp = tmp->prev, i--)
  254.         if (tmp->bid.suit <= RANK_USED)
  255.         {
  256.             if (rank < tmp->bid.rank || 
  257.               rank == tmp->bid.rank &&
  258.               suit_cvt[suit] <= suit_cvt[tmp->bid.suit])
  259.             return(1);
  260.             break;
  261.         }
  262.     }
  263.     /* Make sure double or redouble is valid */
  264.     else if (suit == DOUBLE || suit == REDOUBLE)
  265.     {
  266.     if (pdeal->num_bids <= 0)
  267.         return(1);
  268.         for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
  269.       tmp = tmp->prev, i--)
  270.         if (tmp->bid.suit != PASS)
  271.         {
  272.             /* Double or redouble by wrong side */
  273.         /* The person bidding in the num_bids position was
  274.            an opponent. The last valid bidder must have had
  275.            this parity. */
  276.         if (((i ^ pdeal->num_bids) & 1) == 1)
  277.             return(1);
  278.         /* Double of a double or redouble */
  279.         if (suit == DOUBLE && tmp->bid.suit > RANK_USED)
  280.             return(1);
  281.         /* Redouble of a bid other than double */
  282.         if (suit == REDOUBLE && tmp->bid.suit != DOUBLE)
  283.             return(1);
  284.         break;
  285.         }
  286.     /* Double or redouble as first non-pass bid */
  287.     if (!i)
  288.         return(1);
  289.     }
  290.  
  291.     newbid = (bid *)malloc(sizeof(bid));
  292.     newbid->bid.rank = rank;
  293.     newbid->bid.suit = suit;
  294.  
  295.     if (++(pdeal->num_bids) == 1)
  296.     newbid->next = newbid->prev = pdeal->bids = newbid;
  297.     else
  298.     {
  299.     (newbid->next = pdeal->bids)->prev = 
  300.       (newbid->prev = pdeal->bids->prev)->next = newbid;
  301.     if (newbid->bid.suit == PASS && newbid->prev->bid.suit == PASS &&
  302.       newbid->prev->prev->bid.suit == PASS && pdeal->num_bids >= 4)
  303.         pdeal->bidding_done = 1;
  304.     }
  305.     return(0);
  306. }
  307.  
  308. more()
  309. {
  310.     printf("---Hit return to continue---");
  311.     while (getchar() != '\n');
  312. }
  313.  
  314. log_deal(pdeal,top_hand)
  315. deal *pdeal;
  316. int top_hand;
  317. {
  318.     FILE *fp;
  319.     int i;
  320.  
  321.     if ((fp = fopen(LOGFILE,"a")) == NULL)
  322.     {
  323.     perror(LOGFILE);
  324.     return;
  325.     }
  326.     print_bidding(fp,pdeal,figure_out_leader(pdeal));
  327.     if (pdeal->opening_lead.suit >= 0)
  328.         fprintf(fp,"OPENING LEAD: %c of %s\n",pdeal->opening_lead.rank,
  329.           suit_strings[pdeal->opening_lead.suit]);
  330.     print_complete_deal(fp,pdeal,top_hand);
  331.     putc('\n',fp);
  332.     putc('\n',fp);
  333.     fclose(fp);
  334. }
  335.  
  336. figure_out_leader(pdeal)
  337. deal *pdeal;
  338. {
  339.     int contract_maker;
  340.     bid *finalsuit,*tmp;
  341.     int suit_bidder;
  342.  
  343.     /* Find out which bid specified the basic contract */
  344.     for (contract_maker = pdeal->num_bids - 1, finalsuit = pdeal->bids->prev;
  345.       contract_maker >= 0 && finalsuit->bid.suit > RANK_USED;
  346.       contract_maker--, finalsuit = finalsuit->prev);
  347.     if (contract_maker < 0)
  348.         return(-1);
  349.     /* Reduce this to a single side */
  350.     contract_maker &= 1;
  351.     /* Find the first player of this side to bid this suit. */
  352.     suit_bidder = contract_maker;
  353.     tmp = (suit_bidder) ? pdeal->bids->next : pdeal->bids;
  354.     while (tmp->bid.suit != finalsuit->bid.suit)
  355.     {
  356.         suit_bidder += 2;
  357.     tmp = tmp->next->next;
  358.     }
  359.     return((suit_bidder + 1) % 4);
  360. }
  361.  
  362. get_lead(pdeal,handnum)
  363. deal *pdeal;
  364. int handnum;
  365. {
  366.     int rank,suit,i;
  367.     char *tmp;
  368.     static char valid_ranks[] = "23456789TJQKA";
  369.     static char valid_suits[] = "SHDC";
  370.     
  371.     printf("\nEnter your opening lead: ");
  372.  
  373.     /* Get rank */
  374.     while (isspace(rank = getchar()));
  375.  
  376.     /* Get suit */
  377.     while (isspace(suit = getchar()));
  378.  
  379.     if (islower(rank))
  380.         rank = toupper(rank);
  381.     if (index(valid_ranks,rank) == NULL)
  382.     {
  383.         if (rank == '1' && suit == '0')
  384.     {
  385.         rank = 'T';
  386.         /* Get suit again */
  387.         while (isspace(suit = getchar()));
  388.     }
  389.     else
  390.         rank = -1;
  391.     }
  392.     if (islower(suit))
  393.         suit = toupper(suit);
  394.     if ((tmp = index(valid_suits,suit)) == NULL)
  395.         suit = -1;
  396.     while (getchar() != '\n');
  397.     if (rank < 0 || suit < 0)
  398.         return(1);
  399.  
  400.     pdeal->opening_lead.rank = rank;
  401.     pdeal->opening_lead.suit = tmp - valid_suits;
  402.  
  403.     /* Check to see if it's in the hand */
  404.     for (i = 0; i < 13; i++)
  405.         if (pdeal->hands[handnum][i].suit == pdeal->opening_lead.suit &&
  406.       valid_ranks[pdeal->hands[handnum][i].rank - 2] ==
  407.       pdeal->opening_lead.rank)
  408.         return(0);
  409.     return(1);
  410. }
  411.  
  412. clear_screen()
  413. {
  414. #ifdef SCREEN_CLEAR_SIZE
  415.     int i;
  416.  
  417.     for (i = 0; i < SCREEN_CLEAR_SIZE; i++)
  418.         putchar('\n');
  419. #else
  420.     putchar('\f');
  421. #endif
  422. }
  423.